#pragma once

#include "_xptr_base.h"
#include "xshared_ptr.hpp"
#include "IPALDebuggingServices.h"


template<typename T>
class xweak_ptr :
	public _xptr_base<T>
{
public: 
	xweak_ptr(const xweak_ptr<T> & rhs):
		_xptr_base<T>(rhs)
	{
		this->IncrementRefCount();
	}

	xweak_ptr(const xshared_ptr<T> & rhs):
		_xptr_base<T>(rhs)
	{
		this->IncrementRefCount();
	}

	xweak_ptr() :
		_xptr_base<T>()
	{

	}
	~xweak_ptr()
	{
		this->DecrementRefCount();
	}

	xweak_ptr & operator=(const xweak_ptr<T> & rhs)
	{
		this->DecrementRefCount();
		this->m_pControlBlock = rhs.m_pControlBlock;
		this->m_ptr = rhs.m_ptr;
		this->IncrementRefCount();
		return *this;
	}

	void reset()
	{
		NOTIMPL
	}

	XUINT32 use_count()
	{
		NOTIMPL
	}

	XUINT32 expired() const
	{
		return !this->m_pControlBlock || !this->m_pControlBlock->m_uStrongCount;
	}

	HRESULT lock(xshared_ptr<T> & outSharedPtr) const
	{
		HRESULT hr = S_OK;

		if(this->expired())
		{
			hr = 0x80004005u;
		}
		else
		{
			outSharedPtr.SetFromOtherPointer(*this);
		}

		return hr;
	}
private: 
	void DecrementRefCount()
	{
		if(this->m_pControlBlock)
		{
			XASSERT(this->m_pControlBlock->m_uWeakCount > 0);
			--this->m_pControlBlock->m_uWeakCount;
			if ( this->m_pControlBlock->NoRemainingRefs() )
				this->ReleaseRefCountStorage();
		}
	}

	HRESULT IncrementRefCount()
	{
		if ( this->m_ptr )
		{
			XASSERT(this->m_pControlBlock != NULL);
			++this->m_pControlBlock->m_uWeakCount;
		}
		return S_OK;
	}
};

